﻿using System;
using System.Data;

namespace BasePersistenceNamespace
{
    /// <summary>
    /// 作業を行うための作業スペースを表します。
    /// </summary>
    /// <remarks>
    /// <para>
    /// 作業スペースはデータストアから読み込んだエンティティのキャッシュ・変更追跡を行い、エンティティをデータストアへ永続化します。
    /// </para>
    /// <para>
    /// 作業スペースは、取得後から変更が加えられているエンティティを自動で認識します。
    /// エンティティの追加・削除を行う場合は、予め追加対象・削除対象のエンティティをマークしておく必要があります。
    /// エンティティの追加・変更・削除は、任意のタイミングで一括してデータストアに永続化することができます。
    /// 永続化を行うには <see cref="IWorkspace.PersistAll(IsolationLevel)"/> メソッドを呼び出します。
    /// </para>
    /// <para>
    /// エンティティの取得、追加対象・削除対象のマークを行うには<see cref="IRepository&lt;TEntity&gt;">リポジトリ</see>を使用します。
    /// リポジトリは <see cref="IWorkspace.GetRepository&lt;TEntity&gt;()"/> メソッドを使用して取得します。
    /// </para>
    /// <para>
    /// <see cref="IWorkspace.PersistAll(IsolationLevel)"/> メソッドが例外をスローした場合、
    /// 作業スペースは無効な状態となり <see cref="IWorkspace.PersistAll(IsolationLevel)"/> メソッドの呼び出しやリポジトリ操作が行えなくなります。
    /// クライアントは速やかに <see cref="IWorkspace.Clear()"/> メソッドを呼び出してこの状態から復帰させる必要があります。
    /// <see cref="IWorkspace.Clear()"/> メソッドによって、エンティティのキャッシュは全て破棄され、エンティティと作業スペースの関連がなくなります。
    /// <see cref="IWorkspace.Clear()"/> メソッドを呼び出したら、クライアントはエンティティを捨て処理を最初からやり直す必要があります。
    /// </para>
    /// <para>
    /// 作業スペースの生成は作業スペースファクトリから行います。詳細については <see cref="IWorkspaceFactory"/> を参照してください。
    /// </para>
    /// <note type="note">
    /// 作業スペースの実装クラスは基本機能として実装されているため、主要機能側アセンブリで実装する必要はありません。
    /// </note>
    /// </remarks>
    /// <seealso cref="IRepository&lt;TEntity&gt;"/>
    /// <seealso cref="IWorkspaceFactory"/>
    public interface IWorkspace : IDisposable
    {
        /// <summary>
        /// リポジトリを取得します。
        /// </summary>
        /// <typeparam name="TEntity">エンティティの型。</typeparam>
        /// <returns>リポジトリ。</returns>
        IRepository<TEntity> GetRepository<TEntity>()
            where TEntity : class;

        /// <summary>
        /// 全ての作業をクリアします。
        /// </summary>
        void Clear();

        /// <summary>
        /// 全ての作業をデータストアへ永続化します。
        /// </summary>
        /// <param name="isolationLevel">トランザクション分離レベル。</param>
        /// <exception cref="ConcurrencyException">同時実行が発生しました。</exception>
        void PersistAll(IsolationLevel isolationLevel = IsolationLevel.Unspecified);

        /// <summary>
        /// データストアへ永続化されていない作業があるかどうかを示す値を取得します。
        /// </summary>
        /// <returns>データストアへ永続化されていない作業がある場合は true、それ以外は false。</returns>
        bool IsDirty();
    }
}
